/** 
 * Project Name:jd-orm 
 * File Name:DatasourceRouteImpl.java 
 * Package Name:com.jd.orm.framework.core.datasource.impl 
 * Date:2014-5-12下午8:33:01 
 * Copyright (c) 2014, liubing1@jd.com All Rights Reserved. 
 * 
 */

package com.jd.orm.framework.core.datasource.impl;

import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSource;
import com.jd.orm.framework.configuration.DatasourceConfiguration;
import com.jd.orm.framework.configuration.bean.ConfigurationBean;
import com.jd.orm.framework.configuration.bean.ConfigurationDatasourceBean;
import com.jd.orm.framework.core.datasource.IDatasourceRoute;
import com.jd.orm.framework.core.exception.SysError;
import com.jd.orm.framework.core.exception.SystemException;
import com.jd.orm.framework.core.util.StringUtil;

/**
 * ClassName: DatasourceRouteImpl <br/>
 * Function: Datasource route <br/>
 * Reason: TODO ADD REASON. <br/>
 * date: 2014-5-12 下午8:33:01 <br/>
 * 
 * @author liubing1@jd.com
 * @version
 * @since up JDK 1.5
 */

public class DatasourceRouteImpl implements IDatasourceRoute {

	private static ThreadLocal<DataSource> threadDataSource = new ThreadLocal<DataSource>();

	private static ConcurrentHashMap<String, DataSource> datasourceCache = new ConcurrentHashMap<String, DataSource>();

	private static ThreadLocal<ConfigurationBean> threadConfigurationBean = new ThreadLocal<ConfigurationBean>();

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.jd.orm.framework.core.datasource.IDatasourceRoute#getORMDatasource()
	 */
	public DataSource getORMDatasource() throws Exception{
		// TODO Auto-generated method stub
		if(datasourceCache.keySet().size()>2){
			throw new Exception("more one DataSource exist,please use this method getORMDatasource(String datasourceId)");
		}
		if (!StringUtil.isNullOrEmpty(threadDataSource.get()))
			return threadDataSource.get();
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.jd.orm.framework.core.datasource.IDatasourceRoute#getORMDatasource
	 * (java .lang.String)
	 */
	public DataSource getORMDatasource(String datasourceId) {
		// TODO Auto-generated method stub
		if (!StringUtil.isNullOrEmpty(threadDataSource.get()))
			return datasourceCache.get(datasourceId);
		return null;
	}

	/**
	 * @return the threadDataSource
	 */
	public static ThreadLocal<DataSource> getThreadDataSource() {
		return threadDataSource;
	}

	/**
	 * @param threadDataSource
	 *            the threadDataSource to set
	 */
	public static void setThreadDataSource(
			ThreadLocal<DataSource> threadDataSource) {
		DatasourceRouteImpl.threadDataSource = threadDataSource;
	}

	/**
	 * @return the datasourceCache
	 */
	public static ConcurrentHashMap<String, DataSource> getDatasourceCache() {
		return datasourceCache;
	}

	/**
	 * @param datasourceCache
	 *            the datasourceCache to set
	 */
	public static void setDatasourceCache(
			ConcurrentHashMap<String, DataSource> datasourceCache) {
		DatasourceRouteImpl.datasourceCache = datasourceCache;
	}

	/**
	 * @return the threadConfigurationBean
	 */
	public static ThreadLocal<ConfigurationBean> getThreadConfigurationBean() {
		return threadConfigurationBean;
	}

	/**
	 * @param threadConfigurationBean
	 *            the threadConfigurationBean to set
	 */
	public static void setThreadConfigurationBean(
			ThreadLocal<ConfigurationBean> threadConfigurationBean) {
		DatasourceRouteImpl.threadConfigurationBean = threadConfigurationBean;
	}

	public ConfigurationBean getConfigurationBeanByProperty(String filepath) {
		// TODO Auto-generated method stub
		return DatasourceConfiguration.getConfigurationBean(filepath);
	}

	@SuppressWarnings("unchecked")
	public static void initDataSource(ConfigurationBean configurationBean) {
		// TODO Auto-generated method stub
		try{
			if (configurationBean.getConfigurationDatasourceBeans().size() > 0
					&& configurationBean.getConfigurationDatasourceBeans().size() == 1) {// init datsource,configure one  datasource
																							
				List<ConfigurationDatasourceBean> configurationDatasourceBeans=configurationBean.getConfigurationDatasourceBeans();
				ConfigurationDatasourceBean configurationDatasourceBean=configurationDatasourceBeans.get(0);
				Class<DruidDataSource> dataSourceClass =(Class<DruidDataSource>) Class.forName(configurationDatasourceBean.getDataSourceClassName());
				DruidDataSource dataSource = dataSourceClass.newInstance();
				dataSource.setDriverClassName(configurationDatasourceBean.getDriverClassName());
				dataSource.setInitialSize(configurationDatasourceBean.getInitialSize());
				dataSource.setMaxActive(configurationDatasourceBean.getMaxActive());
				//dataSource.setMaxIdle(configurationDatasourceBean.getMinIdle());
				dataSource.setMaxPoolPreparedStatementPerConnectionSize(configurationDatasourceBean.getMaxPoolPreparedStatementPerConnectionSize());
				dataSource.setUrl(configurationDatasourceBean.getUrl());
				dataSource.setUsername(configurationDatasourceBean.getName());
				dataSource.setPassword(configurationDatasourceBean.getPassword());
				dataSource.setValidationQuery(configurationDatasourceBean.getValidationQuery());
				dataSource.setPoolPreparedStatements(configurationDatasourceBean.getPoolPreparedStatements());
				dataSource.setTimeBetweenEvictionRunsMillis(configurationDatasourceBean.getTimeBetweenEvictionRunsMillis());
				dataSource.setMinEvictableIdleTimeMillis(configurationDatasourceBean.getMinEvictableIdleTimeMillis());
				dataSource.setTestOnBorrow(configurationDatasourceBean.getTestOnBorrow());
				dataSource.setTestOnReturn(configurationDatasourceBean.getTestOnReturn());
				dataSource.setTestWhileIdle(configurationDatasourceBean.getTestWhileIdle());
				Method method=dataSource.getClass().getMethod("init");
            	method.invoke(dataSource);
				threadDataSource.set(dataSource);
				datasourceCache.put(configurationDatasourceBean.getDatasourceId(), dataSource);
			} else if (configurationBean.getConfigurationDatasourceBeans().size() > 1) {// init datsource ,configure more one datasource																		
				List<ConfigurationDatasourceBean> configurationDatasourceBeans=configurationBean.getConfigurationDatasourceBeans();
				for(ConfigurationDatasourceBean configurationDatasourceBean:configurationDatasourceBeans){
					Class<DruidDataSource> dataSourceClass =(Class<DruidDataSource>) Class.forName(configurationDatasourceBean.getDataSourceClassName());
					DruidDataSource dataSource = dataSourceClass.newInstance();
					dataSource.setDriverClassName(configurationDatasourceBean.getDriverClassName());
					dataSource.setInitialSize(configurationDatasourceBean.getInitialSize());
					dataSource.setMaxActive(configurationDatasourceBean.getMaxActive());
					//dataSource.setMaxIdle(configurationDatasourceBean.getMinIdle());
					dataSource.setMaxPoolPreparedStatementPerConnectionSize(configurationDatasourceBean.getMaxPoolPreparedStatementPerConnectionSize());
					dataSource.setUrl(configurationDatasourceBean.getUrl());
					dataSource.setUsername(configurationDatasourceBean.getName());
					dataSource.setPassword(configurationDatasourceBean.getPassword());
					dataSource.setValidationQuery(configurationDatasourceBean.getValidationQuery());
					dataSource.setPoolPreparedStatements(configurationDatasourceBean.getPoolPreparedStatements());
					dataSource.setTimeBetweenEvictionRunsMillis(configurationDatasourceBean.getTimeBetweenEvictionRunsMillis());
					dataSource.setMinEvictableIdleTimeMillis(configurationDatasourceBean.getMinEvictableIdleTimeMillis());
					dataSource.setTestOnBorrow(configurationDatasourceBean.getTestOnBorrow());
					dataSource.setTestOnReturn(configurationDatasourceBean.getTestOnReturn());
					dataSource.setTestWhileIdle(configurationDatasourceBean.getTestWhileIdle());
					//threadDataSource.set(dataSource);
					datasourceCache.put(configurationDatasourceBean.getDatasourceId(), dataSource);
				}
			}
		}catch(Exception e){
			throw SystemException.unchecked(e, SysError.CLASS_NOT_FOUND);
		}
		
	}

	public void setDatasource(String xml) {
		// TODO Auto-generated method stub
		ConfigurationBean configurationBean=DatasourceConfiguration.getConfigurationBean(xml);
		initDataSource(configurationBean);
		
	}

	public void setDatasource(ConfigurationBean configurationBean) {
		// TODO Auto-generated method stub
		initDataSource(configurationBean);
	}
	
	
}
